import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Semaphore;

public class LibraryStaff implements Runnable, ILibraryStaff 
{
	public String name;

	private final Library library;
	private boolean onWork;
	private Timer worktime;
	private Reader servicingReader;
	List<Book> request;
	BookLend returningLend;
	List<BookQuery> search;
	private static Semaphore s = new Semaphore(1);

	public LibraryStaff(String name, Library library) 
	{
		this.name = name;
		this.library = library;
		this.worktime = new Timer();
	}

	private void goToWork()
	{
		try 
		{
			s.acquire();
		} 
		catch (InterruptedException e) { e.printStackTrace(); }
		onWork = true;
		library.registerStaff(this);
		if (!library.isOpen()) {
			library.open();
		}
		//library.registerStaff(this);
		System.out.println("Hey, I[" + name + "] got to work");
		s.release();
		long workhours = Library.DAYTIME
				- (int) (Math.random() * (Library.DAYTIME / 10));
		this.worktime.schedule(new TimerTask() {

			@Override
			public void run() {
				onWork = false;
				synchronized (LibraryStaff.this) {
					LibraryStaff.this.notify();
				}
			}
		}, workhours);
	}

	private void goHome() {
		System.out.println("Hey, I[" + name + "] go home");
		if (library.unregisterStaff(this) == 0) {
			System.out.println("And I[" + name + "] closed the library");
			library.close();
		}
		try {
			Thread.sleep(Library.NIGHTITME);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

	}

	/* (non-Javadoc)
	 * @see ILibraryStaff#searchForBook(Reader, java.util.List)
	 */
	@Override
	public synchronized void searchForBook(Reader r, List<BookQuery> search) {
		servicingReader = r;
		this.search = search;
		notify();
	}

	/* (non-Javadoc)
	 * @see ILibraryStaff#bookRetrieval(Reader, java.util.List)
	 */
	@Override
	public synchronized void bookRetrieval(Reader r, List<Book> request) {
		servicingReader = r;
		this.request = request;
		notify();
	}

	/* (non-Javadoc)
	 * @see ILibraryStaff#bookReturn(Reader, BookLend)
	 */
	@Override
	public synchronized void bookReturn(Reader r, BookLend returningLend) {
		servicingReader = r;
		this.returningLend = returningLend;
		notify();
	}

	public void serviceReader() {
		if (search != null) {
			servicingReader.onBooksFound(library.getBooks(search));
			search = null;
		}
		if (request != null) {
			// servicingReader.onBookLate(library.takeBook(request,servicingReader));
			servicingReader.onBooksLend(library.takeBook(request,
					servicingReader));
			request = null;
		}
		if (returningLend != null) {
			servicingReader.onBookReturn(library.returnBook(returningLend,
					servicingReader));
			returningLend = null;
		}
		servicingReader = null;
	}

	private synchronized void work() {
		while (onWork) {
			if (servicingReader != null) {
				serviceReader();
				library.returnToDuty(this);
			} else {
				try {
					wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}

	public void run() {
		while (true) {
			goToWork();
			work();
			goHome();
		}
	}

}
